﻿using System;
using System.Collections.Generic;
using System.ComponentModel;

namespace Bonehead
{
    public class MethodBindingList : BindingList<ParsedMethod>
    {
        List<ParsedMethod> mList;

        public MethodBindingList(List<ParsedMethod> aSource)
            : base(aSource)
        {
            mList = aSource;
        }

        protected override void ApplySortCore(PropertyDescriptor prop, ListSortDirection direction)
        {
            if (prop.Name == "Name")
            {
                mList.Sort(new NameCompare(direction));
                this.OnListChanged(new ListChangedEventArgs(ListChangedType.ItemMoved, 0));
            }
            else if (prop.Name == "CallCount")
            {
                mList.Sort(new CallCountCompare(direction));
                this.OnListChanged(new ListChangedEventArgs(ListChangedType.ItemMoved, 0));
            }
            else if (prop.Name == "CycleCount")
            {
                mList.Sort(new CycleCountCompare(direction));
                this.OnListChanged(new ListChangedEventArgs(ListChangedType.ItemMoved, 0));
            }
            else if (prop.Name == "MinCycleCount")
            {
                mList.Sort(new MinCycleCountCompare(direction));
                this.OnListChanged(new ListChangedEventArgs(ListChangedType.ItemMoved, 0));
            }
            else if (prop.Name == "MaxCycleCount")
            {
                mList.Sort(new MaxCycleCountCompare(direction));
                this.OnListChanged(new ListChangedEventArgs(ListChangedType.ItemMoved, 0));
            }
            else if (prop.Name == "Transitions")
            {
                mList.Sort(new TransitionsCompare(direction));
                this.OnListChanged(new ListChangedEventArgs(ListChangedType.ItemMoved, 0));
            }
            else if (prop.Name == "ExceptionsThrown")
            {
                mList.Sort(new ExceptionsThrownCompare(direction));
                this.OnListChanged(new ListChangedEventArgs(ListChangedType.ItemMoved, 0));
            }
        }

        protected override void RemoveSortCore()
        {
        }

        protected override bool SupportsSortingCore
        {
            get { return true; }
        }

        #region -- Comparer base --
        private abstract class Comparer : IComparer<ParsedMethod>
        {
            ListSortDirection mDirection;

            public Comparer(ListSortDirection aDirection)
            {
                mDirection = aDirection;
            }

            public int Compare(ParsedMethod x, ParsedMethod y)
            {
                int result;
                if (mDirection == ListSortDirection.Ascending)
                {
                    result = DoCompare(x, y);
                }
                else
                {
                    result = DoCompare(y, x);
                }
                if (result == 0)
                {
                    result = Math.Sign(x.GetHashCode() - y.GetHashCode());
                }
                return result;
            }

            protected abstract int DoCompare(ParsedMethod x, ParsedMethod y);
        }
        #endregion

        private class NameCompare : Comparer
        {
            public NameCompare(ListSortDirection aDirection)
                : base(aDirection)
            { }
            protected override int DoCompare(ParsedMethod x, ParsedMethod y)
            {
                return String.Compare(x.Name, y.Name);
            }
        }

        private class CallCountCompare : Comparer
        {
            public CallCountCompare(ListSortDirection aDirection)
                : base(aDirection)
            { }
            protected override int DoCompare(ParsedMethod x, ParsedMethod y)
            {
                return Math.Sign(x.CallCount - y.CallCount);
            }
        }

        private class CycleCountCompare : Comparer
        {
            public CycleCountCompare(ListSortDirection aDirection)
                : base(aDirection)
            { }
            protected override int DoCompare(ParsedMethod x, ParsedMethod y)
            {
                return Math.Sign(x.CycleCount - y.CycleCount);
            }
        }

        private class MinCycleCountCompare : Comparer
        {
            public MinCycleCountCompare(ListSortDirection aDirection)
                : base(aDirection)
            { }
            protected override int DoCompare(ParsedMethod x, ParsedMethod y)
            {
                return Math.Sign(x.MinCycleCount - y.MinCycleCount);
            }
        }

        private class MaxCycleCountCompare : Comparer
        {
            public MaxCycleCountCompare(ListSortDirection aDirection)
                : base(aDirection)
            { }
            protected override int DoCompare(ParsedMethod x, ParsedMethod y)
            {
                return Math.Sign(x.MaxCycleCount - y.MaxCycleCount);
            }
        }

        private class TransitionsCompare : Comparer
        {
            public TransitionsCompare(ListSortDirection aDirection)
                : base(aDirection)
            { }
            protected override int DoCompare(ParsedMethod x, ParsedMethod y)
            {
                return Math.Sign(x.Transitions - y.Transitions);
            }
        }

        private class ExceptionsThrownCompare : Comparer
        {
            public ExceptionsThrownCompare(ListSortDirection aDirection)
                : base(aDirection)
            { }
            protected override int DoCompare(ParsedMethod x, ParsedMethod y)
            {
                return Math.Sign(x.ExceptionsThrown - y.ExceptionsThrown);
            }
        }
    }
}
